package ordered;

import java.util.NoSuchElementException;

import iterator.Iterator;
import visitor.Visitor;
import wrapper.Comparable;
import container.AbstractSearchableContainer;
import container.ContainerEmptyException;
import enumeration.Enumeration;

public class OrderedListAsDoubleLinkedList extends AbstractSearchableContainer
		implements OrderedList {
	private DoubleLinkedList doubleLinkedList;

	public OrderedListAsDoubleLinkedList() {
		doubleLinkedList = new DoubleLinkedList();
	}

	public void insert(Comparable object) {
		doubleLinkedList.append(object);
		++count;
	}

	public Comparable get(int offset) {
		if (offset < 0 || offset >= count)
			throw new IndexOutOfBoundsException();

		DoubleLinkedList.Element ptr = doubleLinkedList.getHead();
		for (int i = 0; i < offset && ptr != null; ++i)
			ptr = ptr.getNext();
		return (Comparable) ptr.getDatum();
	}

	public boolean isMember(Comparable object) {
		for (DoubleLinkedList.Element ptr = doubleLinkedList.getHead(); ptr != null; ptr = ptr
				.getNext()) {
			if (((Comparable) ptr.getDatum()).isEQ(object))
				return true;
		}
		return false;
	}

	public Comparable find(Comparable arg) {
		for (DoubleLinkedList.Element ptr = doubleLinkedList.getHead(); ptr != null; ptr = ptr
				.getNext()) {
			Comparable object = (Comparable) ptr.getDatum();
			if (object.isEQ(arg))
				return object;
		}
		return null;
	}

	public void withdraw(Comparable object) {
		if (count == 0)
			try {
				throw new ContainerEmptyException();
			} catch (ContainerEmptyException e) {
				System.out.println("A lista está vazia!");
			}
		doubleLinkedList.extract(object);
		--count;
	}

	protected class MyCursor implements Cursor {
		DoubleLinkedList.Element element;

		MyCursor(DoubleLinkedList.Element element) {
			this.element = element;
		}

		public Comparable getDatum() {
			return (Comparable) element.getDatum();
		}

		public void insertAfter(Comparable object) {
			element.insertAfter(object);
			++count;
		}

		public void withdraw() {
			doubleLinkedList.extract(element.getDatum());
			--count;
		}

		public void insertBefore(Comparable object) {
			element.insertBefore(object);
			++count;
		}
	}

	public Cursor findPosition(Comparable arg) {
		DoubleLinkedList.Element ptr;
		for (ptr = doubleLinkedList.getHead(); ptr != null; ptr = ptr.getNext()) {
			Comparable object = (Comparable) ptr.getDatum();
			if (object.isEQ(arg))
				break;
		}
		return new MyCursor(ptr);
	}

	@Override
	protected int compareTo(Comparable arg) {
		// TODO Auto-generated method stub
		return 0;
	}

	@Override
	public void accept(Visitor visitor) {
		doubleLinkedList.accept(visitor);
	}

	@Override
	public Enumeration getEnumeration() {
		return doubleLinkedList.getEnumeration();
	}

	@Override
	public Iterator getIterator() {
		return doubleLinkedList.getIterator();
	}

	@Override
	public void purge() {
		doubleLinkedList.purge();
	}

}
